Skip to content

Conversation

@joboet
Copy link
Member

@joboet joboet commented Oct 23, 2025

The comment about double-free is wrong – we can safely drop both the thread attributes and the thread closure. Here, I've used DropGuard for the attributes and moved the Box::into_raw to just before the pthread_create.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 23, 2025
@rustbot
Copy link
Collaborator

rustbot commented Oct 23, 2025

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

) -> io::Result<Thread> {
let data = Box::into_raw(Box::new(ThreadData { name: name.map(Box::from), f }));
let mut native: libc::pthread_t = mem::zeroed();
let data = Box::new(ThreadData { name: name.map(Box::from), f });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this declaration could be moved down in its entirety. I'm not sure why you only did that for the Box::into_raw part.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mistakenly assumed that the Box::from implementation could panic, in which case this should do as little other work as possible. That's not the case, but I'll still leave it here in case something changes in the future.

Comment on lines +59 to +61
let mut attr = DropGuard::new(&mut attr, |attr| {
assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0)
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps you could add a comment here to explain the relevant considerations of using DropGuard here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I notice is that before, libc::pthread_attr_destroy(attr.as_mut_ptr()) is not called for #[cfg(any(target_os = "espidf", target_os = "nuttx"))], but with this change it will/could be. Is that intended?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is very much intended. The leakage of the current version is a bug. And do you really think that this needs documentation? The DropGuard just makes sure that the attribute structure is destroyed, which is pretty self-explanatory to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The what is clear enough, but the why could use some expanding. If it was completely straightforward, then this bug wouldn't have needed fixing, so I do think explaining why the DropGuard is needed would be good.

return if ret != 0 {
// The thread failed to start and as a result p was not consumed. Therefore, it is
// safe to reconstruct the box so that it gets deallocated.
return if ret == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be the last expression of this function, so maybe does not need return?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is an item (the thread_start function) after this, the return is required by the parser.

Comment on lines 117 to 127
extern "C" fn thread_start(data: *mut libc::c_void) -> *mut libc::c_void {
unsafe {
let data = Box::from_raw(data as *mut ThreadData);
// Next, set up our stack overflow handler which may get triggered if we run
// out of stack.
let _handler = stack_overflow::Handler::new(data.name);
// Finally, let's run some code.
(data.f)();
}
ptr::null_mut()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used on line 107 I think, so maybe move just above there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd find that very confusing, as it would mix the function item together with the logic of new. In any case, I don't want to do it in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants